// $Id: decl.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2008-2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

//
// For platform that has _declspec (primarily windows), we use following for
// import/export declarations
//
#ifdef BOOST_HAS_DECLSPEC
// We need to import/export our code only if the user has specifically asked
// for it by defining XPCOM_DYN_LINK if they want the library to be dynamically
// linked:
#  ifdef XPCOM_DYN_LINK
// Export if this is our own source, otherwise import:
#    ifdef XPCOM_SOURCE
#      define XPCOM_DECL __declspec(dllexport)
#    else
#      define XPCOM_DECL __declspec(dllimport)
#    endif // XPCOM_SOURCE
#  endif // XPCOM_DYN_LINK
#endif // BOOST_HAS_DECLSPEC

//
// If XPCOM_DECL isn't defined yet define it now:
//
#ifndef XPCOM_DECL
#  define XPCOM_DECL
#endif

//
// Visibility attribute
//
#ifdef XPCOM_HAS_VISIBILITY_ATTRIBUTE
#  define XPCOM_VISIBILITY_DEFAULT __attribute__((visibility("default")))
#  define XPCOM_VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
#else
#  define XPCOM_VISIBILITY_DEFAULT
#  define XPCOM_VISIBILITY_HIDDEN
#endif

#define XPCOM_HIDDEN_(type)         XPCOM_VISIBILITY_HIDDEN type
#define XPCOM_EXTERNAL_VIS_(type)   XPCOM_VISIBILITY_DEFAULT type

#define XPCOM_HIDDEN                XPCOM_VISIBILITY_HIDDEN
#define XPCOM_EXTERNAL_VIS          XPCOM_VISIBILITY_DEFAULT

#undef  XPCOM_IMETHOD_VISIBILITY
#define XPCOM_IMETHOD_VISIBILITY    XPCOM_VISIBILITY_HIDDEN

//
// Fast call, see document in nscore.h of mozilla sdk for details
//
#if defined(XPCOM_USE_REGPARM_ATTRIBUTE)
#  define XPCOM_FASTCALL __attribute__((regparm (3), stdcall))
#  define XPCOM_CONSTRUCTOR_FASTCALL __attribute__((regparm (3), stdcall))
#elif defined(XPCOM_PLATFORM_WIN32)
#  define XPCOM_FASTCALL __fastcall
#  define XPCOM_CONSTRUCTOR_FASTCALL
#else
#  define XPCOM_FASTCALL
#  define XPCOM_CONSTRUCTOR_FASTCALL
#endif

//
// XPCOM_DEFCALL undoes the effect of a global regparm/stdcall setting
// so that xptcall works correctly.
//
#if defined(XPCOM_USE_REGPARM_ATTRIBUTE)
#  define XPCOM_DEFCALL __attribute__((regparm (0), cdecl))
#else
#  define XPCOM_DEFCALL
#endif

//
// Platform specific declarations
//
//Win32
#ifdef XPCOM_PLATFORM_WIN32
#  define XPCOM_IMETHOD_(type) virtual type __stdcall
#  define XPCOM_IMETHODIMP_(type) type __stdcall
#  define XPCOM_METHOD_(type) type __stdcall
#  define XPCOM_CALLBACK_(type, name) type (__stdcall *name)
// XXX OS2, not available..
#elif defined(XPCOM_PLATFORM_OS2) && defined(__declspec)
#  define XPCOM_IMETHOD_(type) virtual type
#  define XPCOM_IMETHODIMP_(type) type
#  define XPCOM_METHOD_(type) type
#  define XPCOM_CALLBACK_(type, name) type (*name)
#else
#  define XPCOM_IMETHOD_(type) virtual XPCOM_IMETHOD_VISIBILITY type XPCOM_DEFCALL
#  define XPCOM_IMETHODIMP_(type) type
#  define XPCOM_METHOD_(type) type
#  define XPCOM_CALLBACK_(type, name) type (*name)
#endif

// XXX Here only for XPCOM_LIB_CALLBACK = NSPR_CALLBACK
// Win32
#if defined(XPCOM_PLATFORM_WIN32)
#  define XPCOM_LIB_CALLBACK
// BeOS
#elif defined(XPCOM_PLATFORM_BEOS)
#  define XPCOM_LIB_CALLBACK
// XXX Win16, this is not supported really
#elif defined(XPCOM_PLATFORM_WIN16)
#  if defined(_WINDLL)
#    define XPCOM_LIB_CALLBACK __cdecl __loadds
#  else // this must be .EXE
#    define XPCOM_LIB_CALLBACK __cdecl __loadds
#  endif // _WINDLL
// MacOS
#elif defined(XPCOM_PLATFORM_MACOS)
#  define XPCOM_LIB_CALLBACK
// XXX OS2, not available..
#elif defined(XPCOM_PLATFORM_OS2) && defined(__declspec)
#  define XPCOM_LIB_CALLBACK
// XXX OS2/VACPP, not available..
#elif defined(XPCOM_PLATFORM_OS2_VACPP)
#  define XPCOM_LIB_CALLBACK _Optlink
// Unix
#else
#  define XPCOM_LIB_CALLBACK
#endif // end of platform

//
// Generic API modifiers which return the standard XPCOM result type
//
#define XPCOM_IMETHOD           XPCOM_IMETHOD_( ::xpcom::result_t)
#define XPCOM_IMETHODIMP        XPCOM_IMETHODIMP_( ::xpcom::result_t)
#define XPCOM_METHOD            XPCOM_METHOD_( ::xpcom::result_t)
#define XPCOM_CALLBACK(name)    XPCOM_CALLBACK_( ::xpcom::result_t, name)

//
// XPCOM_EXPORT, for exporting NSGetModule
//
#ifdef BOOST_HAS_DECLSPEC
#  define XPCOM_EXPORT __declspec(dllexport)
#else
#  define XPCOM_EXPORT XPCOM_EXTERNAL_VIS
#endif

//
// Deprecated declarations
//
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#  define XPCOM_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
#  define XPCOM_DEPRECATED __declspec(deprecated)
#else
#  define XPCOM_DEPRECATED
#endif

//
// Attributes defined to help Dehydra GCC analysis
//
#ifdef DEHYDRA_GCC
#  define XPCOM_SCRIPTABLE __attribute__((user("script")))
#else
#  define XPCOM_SCRIPTABLE
#endif

//
// XPCOM_NO_VTABLE used for interface declarations
//
#if defined(_MSC_VER) && _MSC_VER >= 1100
#  define XPCOM_NO_VTABLE __declspec(novtable)
#else
#  define XPCOM_NO_VTABLE
#endif

//
// These macros allow you to give a hint to the compiler about branch
// probability so that it can better optimize.  Use them like this:
//
//  if (XPCOM_LIKELY(v == 1)) {
//    ... expected code path ...
//  }
//
//  if (XPCOM_UNLIKELY(v == 0)) {
//    ... non-expected code path ...
//  }
//
// These macros are guaranteed to always return 0 or 1.
//
#if defined(__GNUC__) && (__GNUC__ > 2)
#  define XPCOM_LIKELY(x)   (__builtin_expect(!!(x), 1))
#  define XPCOM_UNLIKELY(x) (__builtin_expect(!!(x), 0))
#else
#  define XPCOM_LIKELY(x)   (!!(x))
#  define XPCOM_UNLIKELY(x) (!!(x))
#endif

//
// Force inline... some code might need this
//
#ifdef _DEBUG
#  define XPCOM_FORCEINLINE inline
#else
#  ifdef NDEBUG
#    if defined(_MSC_VER)
#      define XPCOM_FORCEINLINE __forceinline
#    elif defined(__GNUC__) && __GNUC__ > 3
#      define XPCOM_FORCEINLINE inline __attribute__((always_inline))
#    else
#      define XPCOM_FORCEINLINE inline
#    endif
#  else
#    define XPCOM_FORCEINLINE inline
#  endif
#endif

//
// External templates support
//
// #ifdef XPCOM_HAS_EXTERN_TEMPLATE
//   XPCOM_EXTERN_TEMPLATE class XPCOM_TEMPLATE_DECL my_class<type>;
// #endif
//
#ifndef XPCOM_NO_EXTERN_TEMPLATE
#  define XPCOM_HAS_EXTERN_TEMPLATE
#  if defined(BOOST_MSVC) || defined(__ICL)
#    ifdef __GNUC__
#      define XPCOM_EXTERN_TEMPLATE __extension__ extern template
#    else
#      if BOOST_MSVC >= 1310 // XXX was BOOST_MSVC > 1310
#        define XPCOM_TEMPLATE_DECL
#      endif
#      define XPCOM_EXTERN_TEMPLATE extern template
#    endif
#    ifndef XPCOM_TEMPLATE_DECL
#      define XPCOM_TEMPLATE_DECL XPCOM_DECL
#    endif
#  elif (defined(__GNUC__) && (__GNUC__ >= 3))
#    define XPCOM_EXTERN_TEMPLATE __extension__ extern template
#    define XPCOM_TEMPLATE_DECL
#  else
#    undef XPCOM_HAS_EXTERN_TEMPLATE
#  endif
#endif // XPCOM_NO_EXTERN_TEMPLATE

// Disable extern template when compiling source
#if defined(XPCOM_HAS_EXTERN_TEMPLATE) && defined(XPCOM_SOURCE)
#  undef XPCOM_HAS_EXTERN_TEMPLATE
#endif

// Shut up the bogus MSVC warning C4661 while building library: no suitable
// definition provided for explicit template instantiation request
//#ifdef XPCOM_SOURCE
//#  ifdef BOOST_MSVC
//#    pragma warning(disable: 4251 4231 4660 4661)
//#  endif
//#endif // XPCOM_SOURCE
